/* *****************************************************************************************************************************
 * (c) J@mBeL.net 2010-2015
 * Author: John Ambeliotis
 * Created: 24 Apr. 2010
 *
 * License:
 *  This file is part of Project jaNET.

    Project jaNET is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Project jaNET is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Project jaNET. If not, see <http://www.gnu.org/licenses/>. */

using System;
using System.IO;
using System.Text;
using System.Collections;
using System.Xml;
using System.Threading;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;

namespace libJanet
{
    public static class Parser
    {
        /// <summary>
        /// returns the status of the parser.
        /// </summary>
        public static volatile bool ParserState = true;
        internal static volatile bool Mute = false;
        private static readonly object _speech_locker = new object();
				
        /// <summary>
        /// args - more than one in-line argument separated by semicolon.
        /// Example: Parse ("judo serial open; judo server start; %checkin%);
        /// </summary>
        /// <param name="args">
        /// A <see cref="System.String"/>
        /// </param>
        /// <returns>
        /// A <see cref="System.String"/>
        /// </returns>
        public static string Parse(this string args)
        {
            return Parse(args, false, false);
        }

        /// <summary>
        /// args - more than one in-line argument separated by semicolon.
        /// Example: Parse ("judo serial open; judo server start; %checkin%);
        /// ReturnAsHTML - In web request it formats the \r\n to html break <br />.
        /// </summary>
        /// <param name="args">
        /// A <see cref="System.String"/>
        /// </param>
        /// <param name="ReturnAsHTML">
        /// A <see cref="System.Boolean"/>
        /// </param>
        /// <returns>
        /// A <see cref="System.String"/>
        /// </returns>
        internal static string Parse(string args, bool ReturnAsHTML, bool disableSpeech)
        {
            if (args.Contains("{mute}") || args.Contains("{widget}"))
            {
                args = args.Replace("{mute}", string.Empty).Replace("{widget}", string.Empty);
                disableSpeech = true;
            }
            if (args.Contains("</lock>"))
                if (ReturnAsHTML)
                    return Judoers.JudoParser(args).Replace("\r", string.Empty).Replace("\n", "<br />");
                else
                    return Judoers.JudoParser(args);
			
            string[] InstructionSet = args.Split(';');
            string results = string.Empty;

            foreach (string Instruction in InstructionSet)
                if (Instruction.Trim() != string.Empty)
                    results += Execute(Instruction.Trim(), disableSpeech);

            if (ReturnAsHTML)
                return results.Replace("<", "&lt;").Replace(">", "&gt;").Replace("\r", string.Empty).Replace("\n", "<br />");
            else
                return results;
        }

        private static string Execute(string arg, bool disableSpeech)
        {
            string output = string.Empty;

            try
            {
                if (arg.Substring(0, 1) == "%"  ||
                    arg.Substring(0, 2) == "./" ||
                    arg.Length >= 4 && (arg.Substring(0, 4) == "judo"))
                        return ParseTokens(arg);

                else
                {
                    XmlNodeList xList = Methods.getInstructionSet(arg.Replace("*", string.Empty));

                    if (xList.Count <= 0 && !arg.Contains("*"))
                    {
                        output = Judoers.IntelParser(arg);
                        if (output == string.Empty)
                        {
                            FileSystem.Log.Append("obj [ Parser.Execute ]: arg [ " + arg + ", not found. ]");
                            output = arg + ", not found.";
                        }
                    }
                    else
                        foreach (XmlNode nodeItem in xList)
                            output += ParseTokens(nodeItem.InnerText) + "\r\n";
                }

                if (Methods.hasInternetConnection() && !disableSpeech)
                {
                    if (!User.Status && output.Trim() != string.Empty && File.Exists(Methods.getApplicationPath() + ".smtpsettings"))
                    {
                        XmlNodeList xList = Methods.getMailHeaders();

                        foreach (XmlNode nodeItem in xList)
                        {
                            Action SendNotification = () => Judoers.JudoParser("judo mail send " + nodeItem.SelectSingleNode("MailFrom").InnerText + " " +
                                                                                                   nodeItem.SelectSingleNode("MailTo").InnerText + " `" +
                                                                                                   nodeItem.SelectSingleNode("MailSubject").InnerText + "` `" +
                                                                                                   output + "`");
                            Process.CallWithTimeout(SendNotification, 10000);
                        }
                    }
                }

                if (output.Trim() != string.Empty && !Mute && !disableSpeech)
                {
                    Thread t = new Thread(() => { SayText(output.Replace("Parser: ", string.Empty)); });
                    t.IsBackground = true;
                    t.Start();
                }

                if (!ParserState)
                {
                    Thread.Sleep(1000);
                    Environment.Exit(0);
                }
                
                return output.Trim() + "\r\n";
            }
            catch (Exception e)
            {
                if (!e.Message.Contains("Parameter name: length"))
                {
                    FileSystem.Log.Append("obj [ Parser.Execute <Exception> ]: " + e.Message);
                    return e.Message;
                }
                return string.Empty;
            }
        }

        /// <summary>
        /// speek something.
        /// </summary>
        /// <param name="sText">
        /// A <see cref="System.String"/>
        /// </param>
        public static void SayText(string sText)
        {
            SayText((object)sText);
        }
               
        private static void SayText(object sText)
        {
            lock (_speech_locker)
            {
                if (OperatingSystem.Version == OperatingSystem.Type.Unix)
                {
                    if (File.Exists("/usr/bin/festival"))
                        Process.Start("festival -b '(SayText " + "\"" + sText.ToString().Replace("_", string.Empty) + "\"" + ")'");
                    else
                        Process.Start("say " + sText.ToString().Replace("_", string.Empty));
                }
                else
                {
                    String jspeechPath = Methods.getApplicationPath() + "jspeech.exe";
                    if (File.Exists(jspeechPath))
                        Process.Start(jspeechPath, sText.ToString().Replace("_", string.Empty));
                }
            }
        }

        private static string ParseTokens(string sValue)
        {
            if (sValue.Contains("%"))
                if (sValue.Substring(0, 1) == "%")
                    return Methods.ToValues(sValue.ToLower()) + "\r\n";
                else
                    sValue = Methods.ToValues(sValue);

            while (sValue.Contains("*"))
            {
                MatchCollection mItems = Regex.Matches(sValue, @"[*][a-zA-Z0-9_-]+");

                if (mItems.Count > 0)
                    foreach (Match matchString in mItems)
                    {
                        if (matchString.Success)
                        {
                            string retval = ParseTokens(Methods.getInstructionSet(matchString.ToString().Trim()).Item(0).InnerText);
                            sValue = sValue.Replace(matchString.ToString().Trim(), retval);
                        }
                    }
                else
                    break;
            }

            if (sValue.Contains("evalBool"))
                sValue = Evaluate(sValue);
            
            if (sValue.Contains("./") || sValue.Contains("judo"))
            {
                if (sValue.Substring(0, 2).Contains("./"))
                {
                    MatchCollection mItems = Regex.Matches(sValue, @"('[^']+')|(`[^`]+`)");

                    String fileName = string.Empty;
                    String arguments = string.Empty;

                    if (mItems.Count == 0)
                        fileName = sValue.Replace("./", string.Empty);
                    else if (mItems.Count == 1)
                        fileName = mItems[0].Value.Replace("`", string.Empty).Replace("'", string.Empty);
                    if (mItems.Count == 2)
                    {
                        fileName = mItems[0].Value.Replace("`", string.Empty).Replace("'", string.Empty);
                        arguments = mItems[1].Value.Replace("`", string.Empty).Replace("'", string.Empty);
                    }

                    return Process.Start(fileName, arguments);
                }
                else if (sValue.Substring(0, 4) == "judo")
                    return sValue.Replace(sValue, Judoers.JudoParser(sValue)); // + "\r\n"; Causing problem to evaluation - need solution
            }
            return sValue;
        }

        private static string Evaluate(string sValue)
        {
            sValue = sValue.Replace("\r", " ").Replace("\n", " ");

            MatchCollection mItems = Regex.Matches(sValue, @"\{(.*?)\}");

            foreach (Match matchString in mItems)
            {
                if (matchString.Success)
                {
                    string[] args = matchString.ToString().Split(';');
                    if (args[0].Contains("*"))
                        args[0] = ParseTokens(args[0]);
                    if (args[0].Contains("evalBool"))
                    {
                        string condition = Methods.ToValues(args[0].Replace("{", string.Empty)
                                                                   .Replace("evalBool", string.Empty)
                                                                   .Replace("(", string.Empty)
                                                                   .Replace(")", string.Empty));
						
                        bool e = false;
						
                        if (condition.Contains("~>")) {
                            string[] vals = Regex.Split(condition, "~>");
                            e = vals[0].ToString().Replace("\"", string.Empty).Contains(vals[1].ToString().Replace("\"", string.Empty));
                        }
                        else
                            e = Evaluator.EvaluateToBool(condition);

                        if (e)
                            sValue = sValue.Replace(matchString.ToString(), Parse(args[1].Replace(" ", ";"), false, true));
                        else
                            sValue = sValue.Replace(matchString.ToString(), Parse(args[2].Replace(" ", ";"), false, true));
                    }
                }
            }
            return sValue;
        }
    }

    static class Judoers
    {
        private static readonly object _serial_locker = new object();
        
        private static string[] SplitArguments(string arg)
        {
            List<String> argList = new List<String>();
            MatchCollection mItems = Regex.Matches(arg, @"(<lock>.*?</lock>)|(""[^""]+"")|('[^']+')|(`[^`]+`)|(\/\*.*?\*\/)|[\S+]+");

            foreach (Match matchString in mItems)
                if (!matchString.Value.Contains("</lock>"))
                    argList.Add(matchString.Value.Replace("/*", string.Empty)
                                                 .Replace("*/", string.Empty)
                                                 .Replace("`", string.Empty)
                                                 .Replace("'", string.Empty)
                                                 .Replace("\"", string.Empty)
                                                 .Trim());
                else
                    argList.Add(matchString.Value.Replace("<lock>", string.Empty)
                                                 .Replace("</lock>", string.Empty)
                                                 .Trim());

            return argList.ToArray();
        }

        internal static string JudoParser(string arg)
        {
            ApplicationSettings appset = new ApplicationSettings();

            string output = string.Empty;
            string[] args;
         
            if (!arg.Contains("</lock>"))
                args = SplitArguments(Methods.ToValues(arg)); // Parse it normally
            else
                args = SplitArguments(arg); // Leave it as is, code container
         
            switch (args[1])
            {
                // TIMER
                case "timer":
                case "sleep":
                  Thread.Sleep(Convert.ToInt32(args[2]));
                  break;
                // SERIAL
                case "serial":
                    Listeners.SerialData = string.Empty;
                    switch (args[2])
                    {
                        case "open":
                            if (args.Count() > 3)
                                Listeners.ActivateSerialPort(args[3]);
                            else
                                Listeners.ActivateSerialPort(string.Empty);
                            Thread.Sleep(50);
                            output = "Serial port state: " + Listeners.port.IsOpen;
                            break;
                        case "close":
                            Listeners.DeactivateSerialPort();
                            Thread.Sleep(50);
                            output = "Serial port state: " + Listeners.port.IsOpen;
                            break;
                        case "send":
                        case "listen":
                        case "monitor":
                            try
                            {
                                lock (_serial_locker)
                                {
                                    if (Listeners.port.IsOpen)
                                    {
                                        if (args[2] == "send")
                                        {
                                            // Clear all buffers
                                            Listeners.port.DiscardInBuffer();
                                            Listeners.port.DiscardOutBuffer();
                                            Listeners.SerialData = string.Empty;
                                            // Send a new argument
                                            Listeners.port.WriteLine(args[3]);
                                            Thread.Sleep(220);
                                        }
                                        Action getSerialData = () =>
                                        {
                                            while (output == string.Empty)
                                            {
                                                output = Listeners.SerialData;
                                                Thread.Sleep(50);
                                            }
                                        };
                                        if ((args[2] == "listen" || args[2] == "monitor") && args.Count() > 3)
                                            Process.CallWithTimeout(getSerialData, Convert.ToInt32(args[3]));
                                        else
                                            Process.CallWithTimeout(getSerialData, 10000);
                                    }
                                    else
                                        output = "Serial port state: " + Listeners.port.IsOpen;
                                }
                            }
                            catch {
                                // Suppress
                            }
                            break;
                        case "set":
                        case "setup":
                            if (args.Count() >= 4)
                                output = Methods.AddToXML(new InstructionSet(args[3]),
                                                                             ApplicationSettings.ApplicationStructure.SystemCommRoot,
                                                                             ApplicationSettings.ApplicationStructure.ComPortElement);
                            if (args.Count() == 5)
                                output = Methods.AddToXML(new InstructionSet(args[4]),
                                                                             ApplicationSettings.ApplicationStructure.SystemCommRoot,
                                                                             ApplicationSettings.ApplicationStructure.ComBaudRateElement);
                            break;
                        case "settings":
                            output = appset.ComPort + "\r\n" + appset.Baud;
                            break;
                        case "state":
                        case "status":
                        default:
                            output = "Serial port state: " + Listeners.port.IsOpen;
                            break;
                    }
                    break;
                // HELP
                case "help":
                case "?":
                    if (args.Count() > 2)
                        output = Methods.getHelp(args[2]);
                    else
                        output = Methods.getHelp("all");
                    break;
                // INSTRUCTION SETS
                case "inset":
                    switch (args[2])
                    {
                        case "add":
                        case "new":
                        case "set":
                        case "setup":
                            if (args.Count() == 5)
                                output = Methods.AddToXML(new InstructionSet(args[3],   // ID
                                                                             args[4]),  //Action
                                                                             ApplicationSettings.ApplicationStructure.SystemInstructionsRoot,
                                                                             "InstructionSet");
                            else
                                output = Methods.AddToXML(new InstructionSet(args[3],   // ID
                                                                             args[4],   //Action
                                                                             args[5].Replace("\"", string.Empty).Replace("'", string.Empty),    // Category
                                                                             args[6].Replace("\"", string.Empty).Replace("'", string.Empty),    // Header
                                                                             args[7].Replace("\"", string.Empty).Replace("'", string.Empty),    // Short Description
                                                                             args[8].Replace("\"", string.Empty).Replace("'", string.Empty),    // Description
                                                                             args[9].Replace("\"", string.Empty).Replace("'", string.Empty),    // Thumbnail Url
                                                                             args[10].Replace("\"", string.Empty).Replace("'", string.Empty)),  // Real Time Data
                                                                             ApplicationSettings.ApplicationStructure.SystemInstructionsRoot,
                                                                             "InstructionSet");
                            break;
                        case "remove":
                        case "rm":
                        case "delete":
                        case "del":
                        case "kill":
                            output = Methods.RemoveFromXML(args[3], ApplicationSettings.ApplicationStructure.SystemInstructionsRoot, "InstructionSet");
                            break;
                        case "list":
                        case "ls":
                        default:
                            XmlNodeList xList = Methods.getXmlElementList(ApplicationSettings.ApplicationStructure.SystemInstructionsRoot, "InstructionSet");
                            foreach (XmlNode nodeItem in xList)
                                output += nodeItem.OuterXml + "\r\n";
                            break;
                    }
                    break;
                // EVENTS
                case "event":
                    switch (args[2])
                    {
                        case "add":
                        case "new":
                        case "set":
                        case "setup":
                            output = Methods.AddToXML(new InstructionSet(args[3],
                                                                         args[4]),
                                                                         ApplicationSettings.ApplicationStructure.SystemEventsRoot,
                                                                         "event");
                            break;
                        case "remove":
                        case "rm":
                        case "delete":
                        case "del":
                        case "kill":
                            output = Methods.RemoveFromXML(args[3], ApplicationSettings.ApplicationStructure.SystemEventsRoot, "event");
                            break;
                        case "list":
                        case "ls":
                        default:
                            XmlNodeList xList = Methods.getXmlElementList(ApplicationSettings.ApplicationStructure.SystemEventsRoot, "event");
                            foreach (XmlNode nodeItem in xList)
                                output += nodeItem.OuterXml + "\r\n";
                            break;
                    }
                    break;
                // SOCKET LISTENING MODE
                case "socket":
                    switch (args[2])
                    {
                        case "on":
                        case "enable":
                        case "start":
                        case "listen":
                        case "open":
                            Server.TCP.Start();
                            Thread.Sleep(50);
                            output = "Socket state: " + Server.TCP.ServerState;
                            break;
                        case "off":
                        case "disable":
                        case "stop":
                        case "close":
                            Server.TCP.Stop();
                            Thread.Sleep(50);
                            output = "Socket state: " + Server.TCP.ServerState;
                            break;
                        case "set":
                        case "setup":
                            if (args.Count() >= 4)
                                output = Methods.AddToXML(new InstructionSet(args[3]),
                                                                             ApplicationSettings.ApplicationStructure.SystemCommRoot,
                                                                             ApplicationSettings.ApplicationStructure.LocalHostElement);
                            if (args.Count() == 5)
                                output = Methods.AddToXML(new InstructionSet(args[4]),
                                                                             ApplicationSettings.ApplicationStructure.SystemCommRoot,
                                                                             ApplicationSettings.ApplicationStructure.LocalPortElement);
                            break;
                        case "settings":
                            output = appset.LocalHost + "\r\n" + appset.LocalPort;
                            break;
                        case "state":
                        case "status":
                        default:
                            output = "Socket state: " + Server.TCP.ServerState;
                            break;
                    }
                    break;
                // WEB SERVER MODE
                case "server":
                    switch (args[2])
                    {
                        case "on":
                        case "enable":
                        case "start":
                        case "listen":
                            Server.Web.Start();
                            Thread.Sleep(50);
                            output = "Web server state: " + Server.Web.httplistener.IsListening;
                            break;
                        case "off":
                        case "disable":
                        case "stop":
                            Server.Web.Stop();
                            Thread.Sleep(50);
                            output = "Web server state: " + Server.Web.httplistener.IsListening;
                            break;
                        case "login":
                        case "cred":
                        case "credentials":
                            output = new FileSystem.Settings().SaveSettings(".htaccess", args[3] + "\r\n" + args[4]);
                            break;
                        case "set":
                        case "setup":
                            if (args.Count() >= 4)
                                output = Methods.AddToXML(new InstructionSet(args[3]),
                                                                             ApplicationSettings.ApplicationStructure.SystemCommRoot,
                                                                             ApplicationSettings.ApplicationStructure.HttpHostNameElement);
                            if (args.Count() >= 5)
                                output = Methods.AddToXML(new InstructionSet(args[4]),
                                                                             ApplicationSettings.ApplicationStructure.SystemCommRoot,
                                                                             ApplicationSettings.ApplicationStructure.HttpPortElement);
                            if (args.Count() == 6)
                                output = Methods.AddToXML(new InstructionSet(args[5]),
                                                                             ApplicationSettings.ApplicationStructure.SystemCommRoot,
                                                                             ApplicationSettings.ApplicationStructure.HttpAuthenticationElement);
                            break;
                        case "settings":
                            output = appset.HostName + "\r\n" + appset.HttpPort + "\r\n" + appset.Authentication;
                            break;
                        case "state":
                        case "status":
                        default:
                            output = "Web server state: " + Server.Web.httplistener.IsListening;
                            break;
                    }
                    break;
                // SCHEDULER
                case "schedule":
                    switch (args[2])
                    {
                        case "add":
                        case "new":
                        case "set":
                        case "setup":
                            Schedule ss = new Schedule();
                            ss.Name = args[3];
                            ss.Date = args[4].ToLower().FixScheduleDate();
                            ss.Time = args[5];
                            ss.Action = args[6].Replace("\"", string.Empty).Replace("'", string.Empty);
                            if (args.Count() > 7)
                                ss.Status = Convert.ToBoolean(args[7]);
                            else
                                ss.Status = Convert.ToBoolean(ScheduleStatus.Enable);
                            
                            if (ss.Date == "repeat" || ss.Date == "interval" || ss.Date == "timer")
                                output = Schedule.Add(ss, Convert.ToInt32(ss.Time));
                            else
                                output = Schedule.Add(ss);
                            break;
                        case "enable":
                        case "activate":
                        case "start":
                        case "on":
                            output = Schedule.ChangeStatus(args[3], ScheduleStatus.Enable);
                            break;
                        case "enable-all":
                        case "activate-all":
                        case "start-all":
                        case "on-all":
                            output = Schedule.ChangeStatus(ScheduleStatus.EnableAll);
                            break;
                        case "disable":
                        case "deactivate":
                        case "stop":
                        case "off":
                            output = Schedule.ChangeStatus(args[3], ScheduleStatus.Disable);
                            break;
                        case "disable-all":
                        case "deactivate-all":
                        case "stop-all":
                        case "off-all":
                            output = Schedule.ChangeStatus(ScheduleStatus.DisableAll);
                            break;
                        case "remove":
                        case "rm":
                        case "delete":
                        case "del":
                            output = Schedule.ChangeStatus(args[3], ScheduleStatus.Remove);
                            break;
                        case "remove-all":
                        case "delete-all":
                        case "del-all":
                        case "cleanup":
                        case "clear":
                        case "empty":
                            output = Schedule.ChangeStatus(ScheduleStatus.RemoveAll);
                            break;
                        case "active":
                        case "actives":
                        case "active-list":
                        case "active-ls":
                        case "list-actives":
                        case "ls-actives":
                            foreach (Schedule schedule in Schedule.ScheduleList)
                                if (schedule.Status == true)
                                    output += schedule.Name + "\r\n";
                            break;
                        case "inactive":
                        case "inactives":
                        case "inactive-list":
                        case "inactive-ls":
                        case "list-inactives":
                        case "ls-inactives":
                            foreach (Schedule schedule in Schedule.ScheduleList)
                                if (schedule.Status == false)
                                    output += schedule.Name + "\r\n";
                            break;
                        case "names":
                        case "name-list":
                        case "name-ls":
                        case "list-names":
                        case "ls-names":
                            foreach (Schedule schedule in Schedule.ScheduleList)
                                output += schedule.Name + "\r\n";
                            break;
                        case "active-details":
                        case "actives-details":
                        case "active-list-details":
                        case "active-ls-details":
                        case "list-actives-details":
                        case "ls-actives-details":
                            foreach (Schedule schedule in Schedule.ScheduleList)
                                if (schedule.Status == true)
                                    output += schedule.Name + " | " + schedule.Date + " | " + schedule.Time + " | " + schedule.Action + " | " + schedule.Status.ToString().ToLower().Replace("true", "Active") + "\r\n";
                            break;
                        case "inactive-details":
                        case "inactives-details":
                        case "inactive-list-details":
                        case "inactive-ls-details":
                        case "list-inactives-details":
                        case "ls-inactives-details":
                            foreach (Schedule schedule in Schedule.ScheduleList)
                                if (schedule.Status == false)
                                    output += schedule.Name + " | " + schedule.Date + " | " + schedule.Time + " | " + schedule.Action + " | " + schedule.Status.ToString().ToLower().Replace("false", "Inactive") + "\r\n";
                            break;
                        case "details":
                        case "state":
                        case "status":
                        case "list":
                        case "ls":
                        default:
                            foreach (Schedule schedule in Schedule.ScheduleList)
                                if (args.Count() > 3)
                                {
                                    if (args[3] == schedule.Name)
                                        output += schedule.Name + " | " + schedule.Date + " | " + schedule.Time + " | " + schedule.Action + " | " + schedule.Status.ToString().ToLower().Replace("true", "Active").Replace("false", "Inactive") + "\r\n";
                                }
                                else
                                    output += schedule.Name + " | " + schedule.Date + " | " + schedule.Time + " | " + schedule.Action + " | " + schedule.Status.ToString().ToLower().Replace("true", "Active").Replace("false", "Inactive") + "\r\n";
                                break;
                    }
                    break;
                // SMTP
                case "smtp":
                    switch (args[2])
                    {
                        case "add":
                        case "setup":
                        case "set":
                            output = new FileSystem.Settings().SaveSettings(".smtpsettings", args[3] + "\r\n" +
                                                                                             args[4] + "\r\n" +
                                                                                             args[5] + "\r\n" +
                                                                                             args[6] + "\r\n" +
                                                                                             args[7]);
                            break;
                        case "settings":
                            Net.Mail.SmtpSettings smtpSettings = new Net.Mail.SmtpSettings();
                            output = smtpSettings.Host + "\r\n" +
                                     smtpSettings.Username + "\r\n" +
                                     smtpSettings.Password + "\r\n" +
                                     smtpSettings.Port + "\r\n" +
                                     smtpSettings.SSL;
                            break;
                    }
                    break;
                // POP3
                case "pop3":
                    switch (args[2])
                    {
                        case "add":
                        case "setup":
                        case "set":
                            output = new FileSystem.Settings().SaveSettings(".pop3settings", args[3] + "\r\n" +
                                                                                             args[4] + "\r\n" +
                                                                                             args[5] + "\r\n" +
                                                                                             args[6] + "\r\n" +
                                                                                             args[7]);
                            break;
                        case "settings":
                            Net.Mail.Pop3Settings pop3Settings = new Net.Mail.Pop3Settings();
                            output = pop3Settings.Host + "\r\n" +
                                     pop3Settings.Username + "\r\n" +
                                     pop3Settings.Password + "\r\n" +
                                     pop3Settings.Port + "\r\n" +
                                     pop3Settings.SSL;
                            break;
                    }
                    break;
                // GMAIL
                case "gmail":
                    switch (args[2])
                    {
                        case "add":
                        case "setup":
                        case "set":
                            output = new FileSystem.Settings().SaveSettings(".gmailsettings", args[3] + "\r\n" + args[4]);
                            break;
                        case "settings":
                            Net.Mail.GmailSettings gmailSettings = new Net.Mail.GmailSettings();
                            output = gmailSettings.Username + "\r\n" +
                                     gmailSettings.Password;
                            break;
                    }
                    break;
                // MAIL
                case "mail":
                    switch (args[2])
                    {
                        case "send":
                            output = new Net.Mail().Send(args[3], args[4], args[5], args[6]).ToString()
                                                   .Replace("True", "Mail sent!").Replace("False", "Mail could not be sent");
                            break;
                    }
                    break;
                // SMS
                case "sms":
                    switch (args[2])
                    {
                        case "add":
                        case "setup":
                        case "set":
                            output = new FileSystem.Settings().SaveSettings(".smssettings", args[3] + "\r\n" +
                                                                                            args[4] + "\r\n" +
                                                                                            args[5]);
                            break;
                        case "settings":
                            SMS.SmsSettings smsSettings = new SMS.SmsSettings();
                            output = smsSettings.SmsAPI + "\r\n" +
                                     smsSettings.SmsUsername + "\r\n" +
                                     smsSettings.SmsPassword;
                            break;
                        case "send":
                            output = new SMS().Send(args[3], args[4]);
                            break;
                    }
                    break;
                // WEB API
                case "json":
                    switch (args[2])
                    {
                        case "add":
                        case "new":
                        case "set":
                        case "setup":
                            output = Methods.AddToXML(new InstructionSet(args[3], // ID
                                                                        "judo json get " + Server.Web.SimpleUriEncode(args[4]) + " " + args[5]), //Action
                                                                        ApplicationSettings.ApplicationStructure.SystemInstructionsRoot,
                                                                        "InstructionSet");
                            break;
                        case "get":
                        case "response":
                        case "consume":
                        case "extract":
                            output = new Queries.Json().SelectSingleNode(Server.Web.SimpleUriDecode(args[3]), args[4]);
                            break;
                    }
                    break;
                // WEB SERVICE
                case "xml":
                    switch (args[2])
                    {
                        case "add":
                        case "new":
                        case "set":
                        case "setup":
                            if (args.Count() == 6)
                                output = Methods.AddToXML(new InstructionSet(args[3], // ID
                                                                            "judo xml get " + Server.Web.SimpleUriEncode(args[4]) + " " + args[5]), //Action
                                                                            ApplicationSettings.ApplicationStructure.SystemInstructionsRoot,
                                                                            "InstructionSet");
                            else if (args.Count() == 7)
                                output = Methods.AddToXML(new InstructionSet(args[3], // ID
                                                                            "judo xml get " + Server.Web.SimpleUriEncode(args[4]) + " " + args[5] + " " + args[6]), //Action
                                                                            ApplicationSettings.ApplicationStructure.SystemInstructionsRoot,
                                                                            "InstructionSet");
                            else if (args.Count() == 8)
                                output = Methods.AddToXML(new InstructionSet(args[3], // ID
                                                                            "judo xml get " + Server.Web.SimpleUriEncode(args[4]) + " " + args[5] + " " + args[6] + " " + args[7]), //Action
                                                                            ApplicationSettings.ApplicationStructure.SystemInstructionsRoot,
                                                                            "InstructionSet");
                            break;
                        case "get":
                        case "response":
                        case "consume":
                        case "extract":
                            if (args.Count() == 5)
                                    output = Queries.Xml.SelectSingleNode(Server.Web.SimpleUriDecode(args[3]), args[4]);
                            else if (args.Count() == 6)
                                if (args[4].Contains("="))
                                    output = Queries.Xml.SelectNodes(Server.Web.SimpleUriDecode(args[3]), args[4], args[5])[0];
                                else
                                    output = Queries.Xml.SelectSingleNode(Server.Web.SimpleUriDecode(args[3]), args[4], Convert.ToInt32(args[5]));
                            else if (args.Count() == 7)
                                    output = Queries.Xml.SelectNodes(Server.Web.SimpleUriDecode(args[3]), args[4], args[5])[Convert.ToInt32(args[6])];
                            break;
                    }
                    break;
                // WEATHER
                case "weather":
                    switch (args[2])
                    {
                        case "set":
                        case "setup":
                            output = Methods.AddToXML(new InstructionSet(args[3]),
                                                                         ApplicationSettings.ApplicationStructure.SystemOthersRoot,
                                                                         ApplicationSettings.ApplicationStructure.YahooWeatherFeed);
                            break;
                        case "settings":
                            output = appset.YahooWeather;
                            break;
                    }
                    break;
                // PINGER
                case "ping":
                    output = Methods.Ping(args[2]).ToString();
                    break;
            }
            return output;
        }

        internal static string IntelParser(string arg)
        {
            string output = string.Empty;
            string tmpSchedule = "schedule-" + Methods.getDay() + Methods.getCalendarYear() + "_" + Methods.getHour() + Methods.getMinute() + DateTime.Now.Second;
            
            arg = arg.ToLower();

            if (arg.Contains("set alarm at") || arg.Contains("set an alarm for") || arg.Contains("set alarm for"))
            {
                string t = arg.Replace("set alarm at", string.Empty).Replace(".", string.Empty)
                              .Replace("set an alarm for", string.Empty).Replace(".", string.Empty)
                              .Replace("set alarm for", string.Empty).Replace(".", string.Empty)
                              .Trim();
                string when = "%calendardate%";

                if (Convert.ToInt32(t.ToHour24().Substring(0, t.ToHour24().IndexOf(':'))) < DateTime.Now.Hour ||
                    Convert.ToInt32(t.ToHour24().Substring(0, t.ToHour24().IndexOf(':'))) >= DateTime.Now.Hour && Convert.ToInt32(t.ToHour24().Substring(t.ToHour24().IndexOf(':') + 1)) < DateTime.Now.Minute)
                        when = String.Format("{0:d/M/yyyy}", DateTime.Now.AddDays(1).Date); ;

                Judoers.JudoParser("judo schedule add " + tmpSchedule + " " + when + " " + t.ToHour24() + " __SYS_ALARM");
                output = "Setting alarm for " + t;
            }
            if (arg.Contains("repeat after me"))
                Parser.SayText(arg.Replace("repeat after me", string.Empty).Trim());

            return output;
        }
    }
}